﻿using EBA.Dynamic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;

namespace EBA.Tests.Dynamic
{
    [TestClass]
    public class DynamicObjectMethodTest
    {
        [TestMethod]
        public void Test_ExpandoObject_Action_With_Zero_Parameter()
        {
            var ret = "";
            dynamic obj = new ExpandoObject();

            obj.TestAction = new Action(() => ret = "TestAction");

            var mock = ((object)obj).DynamicCastTo<IDynamicObject>();
            mock.TestAction();
            Assert.AreEqual("TestAction", ret);
        }

        [TestMethod]
        public void Test_ExpandoObject_Action_With_One_Parameter()
        {
            var ret = "";
            dynamic obj = new ExpandoObject();

            obj.TestAction = new Action<string>((a) => ret = "a");

            var mock = ((object)obj).DynamicCastTo<IDynamicObject>();
            mock.TestAction("a");
            Assert.AreEqual("a", ret);
        }

        [TestMethod]
        public void Test_ExpandoObject_Action_With_Parameters()
        {
          string ret = "";
            dynamic obj = new ExpandoObject();

            obj.TestAction = new Action<string, int>((arg1, arg2) => ret = string.Format("{0},{1}",arg1,arg2));

            var mock = ((object)obj).DynamicCastTo<IDynamicObject>();
            mock.TestAction("a",1);
            Assert.AreEqual("a,1", ret);
        }


        [TestMethod]
        public void Test_ExpandoObject_Function_With_Zero_Parameter()
        {
            dynamic obj = new ExpandoObject();
            obj.TestFunction = new Func<string>(() => "a");

            var mock = ((object)obj).DynamicCastTo<IDynamicObject>();

            Assert.AreEqual(obj.TestFunction(), mock.TestFunction());
        }

        [TestMethod]
        public void Test_ExpandoObject_Function_With_One_Parameter()
        {
            dynamic obj = new ExpandoObject();
            obj.TestFunction = new Func<string,string>((a) => a);
            var mock = ((object)obj).DynamicCastTo<IDynamicObject>();

            Assert.AreEqual(obj.TestFunction("s"), mock.TestFunction("s"));
        }


        [TestMethod]
        public void Test_ExpandoObject_Function_With_Parameters()
        {
            dynamic obj = new ExpandoObject();
            obj.TestFunction = new Func<string, int,string>((arg1,arg2) => string.Format("{0},{1}",arg1,arg2));
            var mock = ((object)obj).DynamicCastTo<IDynamicObject>();

            Assert.AreEqual(obj.TestFunction("s", 1), mock.TestFunction("s", 1));
        }

        [TestMethod]
        public void Test_ExpandoObject_Function_With_Custom_Parameters_And_Return_Custom_Object()
        {
            var custom = new CustomObject { };
            dynamic obj = new ExpandoObject();
            obj.TestFunction = new Func<CustomObject,CustomObject>((a) => a);

            var mock = ((object)obj).DynamicCastTo<IDynamicObject>();

            Assert.ReferenceEquals(custom, mock.TestFunction(custom));
        }


        public interface IDynamicObject
        {
            void TestAction();
            void TestAction(string arg1);
            void TestAction(string arg1, int arg2);

            string TestFunction();
            string TestFunction(string s);
            string TestFunction(string arg1, int arg2);

            CustomObject TestFunction(CustomObject obj);
        }

        public class CustomObject
        {
        }

    }
}
